+++ /dev/null
-// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-
-const GLib = imports.gi.GLib;
-const Gio = imports.gi.Gio;
-const Shell = imports.gi.Shell;
-const Lang = imports.lang;
-const Mainloop = imports.mainloop;
-const Signals = imports.signals;
-const St = imports.gi.St;
-
-const DND = imports.ui.dnd;
-const Main = imports.ui.main;
-const Params = imports.misc.params;
-const Search = imports.ui.search;
-const Util = imports.misc.util;
-
-/**
- * Represents a place object, which is most normally a bookmark entry,
- * a mount/volume, or a special place like the Home Folder, Computer, and Network.
- *
- * @name: String title
- * @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
- * @launch: A JavaScript callback to launch the entry
- */
-const PlaceInfo = new Lang.Class({
- Name: 'PlaceInfo',
-
- _init: function(id, name, iconFactory, launch) {
- this.id = id;
- this.name = name;
- this._lowerName = name.toLowerCase();
- this.iconFactory = iconFactory;
- this.launch = launch;
- },
-
- matchTerms: function(terms) {
- let mtype = Search.MatchType.NONE;
- for (let i = 0; i < terms.length; i++) {
- let term = terms[i];
- let idx = this._lowerName.indexOf(term);
- if (idx == 0) {
- mtype = Search.MatchType.PREFIX;
- } else if (idx > 0) {
- if (mtype == Search.MatchType.NONE)
- mtype = Search.MatchType.SUBSTRING;
- } else {
- return Search.MatchType.NONE;
- }
- }
- return mtype;
- },
-
- isRemovable: function() {
- return false;
- }
-});
-
-// Helper function to translate launch parameters into a GAppLaunchContext
-function _makeLaunchContext(params)
-{
- params = Params.parse(params, { workspace: -1,
- timestamp: 0 });
-
- let launchContext = global.create_app_launch_context();
- if (params.workspace != -1)
- launchContext.set_desktop(params.workspace);
- if (params.timestamp != 0)
- launchContext.set_timestamp(params.timestamp);
-
- return launchContext;
-}
-
-const PlaceDeviceInfo = new Lang.Class({
- Name: 'PlaceDeviceInfo',
- Extends: PlaceInfo,
-
- _init: function(mount) {
- this._mount = mount;
- this.name = mount.get_name();
- this._lowerName = this.name.toLowerCase();
- this.id = 'mount:' + mount.get_root().get_uri();
- },
-
- iconFactory: function(size) {
- let icon = this._mount.get_icon();
- return St.TextureCache.get_default().load_gicon(null, icon, size);
- },
-
- launch: function(params) {
- Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
- _makeLaunchContext(params));
- },
-
- isRemovable: function() {
- return this._mount.can_unmount();
- },
-
- remove: function() {
- if (!this.isRemovable())
- return;
-
- if (this._mount.can_eject())
- this._mount.eject(0, null, Lang.bind(this, this._removeFinish));
- else
- this._mount.unmount(0, null, Lang.bind(this, this._removeFinish));
- },
-
- _removeFinish: function(o, res, data) {
- try {
- if (this._mount.can_eject())
- this._mount.eject_finish(res);
- else
- this._mount.unmount_finish(res);
- } catch (e) {
- let message = _("Failed to unmount '%s'").format(o.get_name());
- Main.overview.setMessage(message,
- Lang.bind(this, this.remove),
- _("Retry"));
- }
- }
-});
-
-const PlacesManager = new Lang.Class({
- Name: 'PlacesManager',
-
- _init: function() {
- this._defaultPlaces = [];
- this._mounts = [];
- this._bookmarks = [];
-
- let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
- let homeUri = homeFile.get_uri();
- let homeLabel = Shell.util_get_label_for_uri (homeUri);
- let homeIcon = Shell.util_get_icon_for_uri (homeUri);
- this._home = new PlaceInfo('special:home', homeLabel,
- function(size) {
- return St.TextureCache.get_default().load_gicon(null, homeIcon, size);
- },
- function(params) {
- Gio.app_info_launch_default_for_uri(homeUri, _makeLaunchContext(params));
- });
-
- let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
- let desktopFile = Gio.file_new_for_path (desktopPath);
- let desktopUri = desktopFile.get_uri();
- let desktopLabel = Shell.util_get_label_for_uri (desktopUri);
- let desktopIcon = Shell.util_get_icon_for_uri (desktopUri);
- this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel,
- function(size) {
- return St.TextureCache.get_default().load_gicon(null, desktopIcon, size);
- },
- function(params) {
- Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params));
- });
-
- this._defaultPlaces.push(this._home);
- this._defaultPlaces.push(this._desktopMenu);
-
- /*
- * Show devices, code more or less ported from nautilus-places-sidebar.c
- */
- this._volumeMonitor = Gio.VolumeMonitor.get();
- this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
- this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
- this._updateDevices();
-
- this._bookmarksPath = GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']);
- this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
- this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
- this._bookmarkTimeoutId = 0;
- this._monitor.connect('changed', Lang.bind(this, function () {
- if (this._bookmarkTimeoutId > 0)
- return;
- /* Defensive event compression */
- this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
- this._bookmarkTimeoutId = 0;
- this._reloadBookmarks();
- return false;
- }));
- }));
-
- this._reloadBookmarks();
- },
-
- _updateDevices: function() {
- this._mounts = [];
-
- /* first go through all connected drives */
- let drives = this._volumeMonitor.get_connected_drives();
- for (let i = 0; i < drives.length; i++) {
- let volumes = drives[i].get_volumes();
- for(let j = 0; j < volumes.length; j++) {
- let mount = volumes[j].get_mount();
- if(mount != null) {
- this._addMount(mount);
- }
- }
- }
-
- /* add all volumes that is not associated with a drive */
- let volumes = this._volumeMonitor.get_volumes();
- for(let i = 0; i < volumes.length; i++) {
- if(volumes[i].get_drive() != null)
- continue;
-
- let mount = volumes[i].get_mount();
- if(mount != null) {
- this._addMount(mount);
- }
- }
-
- /* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
- let mounts = this._volumeMonitor.get_mounts();
- for(let i = 0; i < mounts.length; i++) {
- if(mounts[i].is_shadowed())
- continue;
-
- if(mounts[i].get_volume())
- continue;
-
- this._addMount(mounts[i]);
- }
-
- /* We emit two signals, one for a generic 'all places' update
- * and the other for one specific to mounts. We do this because
- * clients like PlaceDisplay may only care about places in general
- * being updated while clients like DashPlaceDisplay care which
- * specific type of place got updated.
- */
- this.emit('mounts-updated');
- this.emit('places-updated');
-
- },
-
- _reloadBookmarks: function() {
-
- this._bookmarks = [];
-
- if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
- return;
-
- let bookmarksContent = Shell.get_file_contents_utf8_sync(this._bookmarksPath);
-
- let bookmarks = bookmarksContent.split('\n');
-
- let bookmarksToLabel = {};
- let bookmarksOrder = [];
- for (let i = 0; i < bookmarks.length; i++) {
- let bookmarkLine = bookmarks[i];
- let components = bookmarkLine.split(' ');
- let bookmark = components[0];
- if (bookmark in bookmarksToLabel)
- continue;
- let label = null;
- if (components.length > 1)
- label = components.slice(1).join(' ');
- bookmarksToLabel[bookmark] = label;
- bookmarksOrder.push(bookmark);
- }
-
- for (let i = 0; i < bookmarksOrder.length; i++) {
- let bookmark = bookmarksOrder[i];
- let label = bookmarksToLabel[bookmark];
- let file = Gio.file_new_for_uri(bookmark);
- if (!file.query_exists(null))
- continue;
- if (label == null)
- label = Shell.util_get_label_for_uri(bookmark);
- if (label == null)
- continue;
- let icon = Shell.util_get_icon_for_uri(bookmark);
-
- let item = new PlaceInfo('bookmark:' + bookmark, label,
- function(size) {
- return St.TextureCache.get_default().load_gicon(null, icon, size);
- },
- function(params) {
- Gio.app_info_launch_default_for_uri(bookmark, _makeLaunchContext(params));
- });
- this._bookmarks.push(item);
- }
-
- /* See comment in _updateDevices for explanation why there are two signals. */
- this.emit('bookmarks-updated');
- this.emit('places-updated');
- },
-
- _addMount: function(mount) {
- let devItem = new PlaceDeviceInfo(mount);
- this._mounts.push(devItem);
- },
-
- getAllPlaces: function () {
- return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts());
- },
-
- getDefaultPlaces: function () {
- return this._defaultPlaces;
- },
-
- getBookmarks: function () {
- return this._bookmarks;
- },
-
- getMounts: function () {
- return this._mounts;
- },
-
- _lookupIndexById: function(sourceArray, id) {
- for (let i = 0; i < sourceArray.length; i++) {
- let place = sourceArray[i];
- if (place.id == id)
- return i;
- }
- return -1;
- },
-
- lookupPlaceById: function(id) {
- let colonIdx = id.indexOf(':');
- let type = id.substring(0, colonIdx);
- let sourceArray = null;
- if (type == 'special')
- sourceArray = this._defaultPlaces;
- else if (type == 'mount')
- sourceArray = this._mounts;
- else if (type == 'bookmark')
- sourceArray = this._bookmarks;
- return sourceArray[this._lookupIndexById(sourceArray, id)];
- },
-
- _removeById: function(sourceArray, id) {
- sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
- }
-});
-Signals.addSignalMethods(PlacesManager.prototype);
-
-const PlaceSearchProvider = new Lang.Class({
- Name: 'PlaceSearchProvider',
- Extends: Search.SearchProvider,
-
- _init: function() {
- this.parent(_("PLACES & DEVICES"));
- this.placesManager = new PlacesManager();
- },
-
- getResultMetas: function(resultIds, callback) {
- let metas = [];
- for (let i = 0; i < resultIds.length; i++) {
- let placeInfo = this.placesManager.lookupPlaceById(resultIds[i]);
- if (!placeInfo)
- metas.push(null);
- else
- metas.push({ 'id': resultIds[i],
- 'name': placeInfo.name,
- 'createIcon': function(size) {
- return placeInfo.iconFactory(size);
- }
- });
- }
- callback(metas);
- },
-
- activateResult: function(id, params) {
- let placeInfo = this.placesManager.lookupPlaceById(id);
- placeInfo.launch(params);
- },
-
- _compareResultMeta: function (idA, idB) {
- let infoA = this.placesManager.lookupPlaceById(idA);
- let infoB = this.placesManager.lookupPlaceById(idB);
- return infoA.name.localeCompare(infoB.name);
- },
-
- _searchPlaces: function(places, terms) {
- let prefixResults = [];
- let substringResults = [];
-
- terms = terms.map(String.toLowerCase);
-
- for (let i = 0; i < places.length; i++) {
- let place = places[i];
- let mtype = place.matchTerms(terms);
- if (mtype == Search.MatchType.PREFIX)
- prefixResults.push(place.id);
- else if (mtype == Search.MatchType.SUBSTRING)
- substringResults.push(place.id);
- }
- prefixResults.sort(Lang.bind(this, this._compareResultMeta));
- substringResults.sort(Lang.bind(this, this._compareResultMeta));
-
- this.searchSystem.pushResults(this, prefixResults.concat(substringResults));
- },
-
- getInitialResultSet: function(terms) {
- let places = this.placesManager.getAllPlaces();
- this._searchPlaces(places, terms);
- },
-
- getSubsearchResultSet: function(previousResults, terms) {
- let places = previousResults.map(Lang.bind(this, function(id) {
- return this.placesManager.lookupPlaceById(id);
- }));
- this._searchPlaces(places, terms);
- }
-});
#include <systemd/sd-login.h>
#endif
-/* Some code in this file adapted under the GPLv2+ from:
- *
- * GNOME panel utils: gnome-panel/gnome-panel/panel-util.c
- * (C) 1997, 1998, 1999, 2000 The Free Software Foundation
- * Copyright 2000 Helix Code, Inc.
- * Copyright 2000,2001 Eazel, Inc.
- * Copyright 2001 George Lebl
- * Copyright 2002 Sun Microsystems Inc.
- *
- * Authors: George Lebl
- * Jacob Berkman
- * Mark McLoughlin
- */
-
-static GFile *
-shell_util_get_gfile_root (GFile *file)
-{
- GFile *parent;
- GFile *parent_old;
-
- /* search for the root on the URI */
- parent_old = g_object_ref (file);
- parent = g_file_get_parent (file);
- while (parent != NULL)
- {
- g_object_unref (parent_old);
- parent_old = parent;
- parent = g_file_get_parent (parent);
- }
-
- return parent_old;
-}
-
-static char *
-shell_util_get_file_display_name_if_mount (GFile *file)
-{
- GFile *compare;
- GVolumeMonitor *monitor;
- GList *mounts, *l;
- char *ret;
-
- ret = NULL;
-
- /* compare with all mounts */
- monitor = g_volume_monitor_get ();
- mounts = g_volume_monitor_get_mounts (monitor);
- for (l = mounts; l != NULL; l = l->next)
- {
- GMount *mount;
- mount = G_MOUNT(l->data);
- compare = g_mount_get_root (mount);
- if (!ret && g_file_equal (file, compare))
- ret = g_mount_get_name (mount);
- g_object_unref (mount);
- }
- g_list_free (mounts);
- g_object_unref (monitor);
-
- return ret;
-}
-
-static char *
-shell_util_get_file_display_for_common_files (GFile *file)
-{
- GFile *compare;
-
- compare = g_file_new_for_path (g_get_home_dir ());
- if (g_file_equal (file, compare))
- {
- g_object_unref (compare);
- /* Translators: this is the same string as the one found in
- * nautilus */
- return g_strdup (_("Home"));
- }
- g_object_unref (compare);
-
- compare = g_file_new_for_path ("/");
- if (g_file_equal (file, compare))
- {
- g_object_unref (compare);
- /* Translators: this is the same string as the one found in
- * nautilus */
- return g_strdup (_("File System"));
- }
- g_object_unref (compare);
-
- return NULL;
-}
-
-static char *
-shell_util_get_file_description (GFile *file)
-{
- GFileInfo *info;
- char *ret;
-
- ret = NULL;
-
- info = g_file_query_info (file, "standard::description",
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
-
- if (info)
- {
- ret = g_strdup (g_file_info_get_attribute_string(info,
- G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION));
- g_object_unref (info);
- }
-
- return ret;
-}
-
-static char *
-shell_util_get_file_display_name (GFile *file, gboolean use_fallback)
-{
- GFileInfo *info;
- char *ret;
-
- ret = NULL;
-
- info = g_file_query_info (file, "standard::display-name",
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
-
- if (info)
- {
- ret = g_strdup (g_file_info_get_display_name (info));
- g_object_unref (info);
- }
-
- if (!ret && use_fallback)
- {
- /* can happen with URI schemes non supported by gvfs */
- char *basename;
-
- basename = g_file_get_basename (file);
- ret = g_filename_display_name (basename);
- g_free (basename);
- }
-
- return ret;
-}
-
-static GIcon *
-shell_util_get_file_icon_if_mount (GFile *file)
-{
- GFile *compare;
- GVolumeMonitor *monitor;
- GList *mounts, *l;
- GIcon *ret;
-
- ret = NULL;
-
- /* compare with all mounts */
- monitor = g_volume_monitor_get ();
- mounts = g_volume_monitor_get_mounts (monitor);
- for (l = mounts; l != NULL; l = l->next)
- {
- GMount *mount;
- mount = G_MOUNT (l->data);
- compare = g_mount_get_root (mount);
- if (!ret && g_file_equal (file, compare))
- {
- ret = g_mount_get_icon (mount);
- }
- g_object_unref (mount);
- }
- g_list_free (mounts);
- g_object_unref (monitor);
-
- return ret;
-}
-
-static const char *
-shell_util_get_icon_for_uri_known_folders (const char *uri)
-{
- const char *icon;
- char *path;
- int len;
-
- icon = NULL;
-
- if (!g_str_has_prefix (uri, "file:"))
- return NULL;
-
- path = g_filename_from_uri (uri, NULL, NULL);
-
- len = strlen (path);
- if (path[len] == '/')
- path[len] = '\0';
-
- if (strcmp (path, "/") == 0)
- icon = "drive-harddisk";
- else if (strcmp (path, g_get_home_dir ()) == 0)
- icon = "user-home";
- else if (strcmp (path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP))
- == 0)
- icon = "user-desktop";
-
- g_free (path);
-
- return icon;
-}
-
-/* This is based on nautilus_compute_title_for_uri() and
- * nautilus_file_get_display_name_nocopy() */
-char *
-shell_util_get_label_for_uri (const char *text_uri)
-{
- GFile *file;
- char *label;
- GFile *root;
- char *root_display;
-
- /* Here's what we do:
- * + x-nautilus-search: URI
- * + check if the URI is a mount
- * + if file: URI:
- * - check for known file: URI
- * - check for description of the GFile
- * - use display name of the GFile
- * + else:
- * - check for description of the GFile
- * - if the URI is a root: "root displayname"
- * - else: "root displayname: displayname"
- */
-
- label = NULL;
-
- //FIXME: see nautilus_query_to_readable_string() to have a nice name
- if (g_str_has_prefix (text_uri, "x-nautilus-search:"))
- return g_strdup (_("Search"));
-
- file = g_file_new_for_uri (text_uri);
-
- label = shell_util_get_file_display_name_if_mount (file);
- if (label)
- {
- g_object_unref (file);
- return label;
- }
-
- if (g_str_has_prefix (text_uri, "file:"))
- {
- label = shell_util_get_file_display_for_common_files (file);
- if (!label)
- label = shell_util_get_file_description (file);
- if (!label)
- label = shell_util_get_file_display_name (file, TRUE);
- g_object_unref (file);
-
- return label;
- }
-
- label = shell_util_get_file_description (file);
- if (label)
- {
- g_object_unref (file);
- return label;
- }
-
- root = shell_util_get_gfile_root (file);
- root_display = shell_util_get_file_description (root);
- if (!root_display)
- root_display = shell_util_get_file_display_name (root, FALSE);
- if (!root_display)
- /* can happen with URI schemes non supported by gvfs */
- root_display = g_file_get_uri_scheme (root);
-
- if (g_file_equal (file, root))
- label = root_display;
- else
- {
- char *displayname;
-
- displayname = shell_util_get_file_display_name (file, TRUE);
- /* Translators: the first string is the name of a gvfs
- * method, and the second string is a path. For
- * example, "Trash: some-directory". It means that the
- * directory called "some-directory" is in the trash.
- */
- label = g_strdup_printf (_("%1$s: %2$s"),
- root_display, displayname);
- g_free (root_display);
- g_free (displayname);
- }
-
- g_object_unref (root);
- g_object_unref (file);
-
- return label;
-}
-
-/**
- * shell_util_get_icon_for_uri:
- * @text_uri: A URI
- *
- * Look up the icon that should be associated with a given URI. Handles
- * various special GNOME-internal cases like x-nautilus-search, etc.
- *
- * Return Value: (transfer full): A new #GIcon
- */
-GIcon *
-shell_util_get_icon_for_uri (const char *text_uri)
-{
- const char *name;
- GFile *file;
- GFileInfo *info;
- GIcon *retval;
-
- /* Here's what we do:
- * + check for known file: URI
- * + x-nautilus-search: URI
- * + override burn: URI icon
- * + check if the URI is a mount
- * + override trash: URI icon for subfolders
- * + check for application/x-gnome-saved-search mime type and override
- * icon of the GFile
- * + use icon of the GFile
- */
-
- /* this only checks file: URI */
- name = shell_util_get_icon_for_uri_known_folders (text_uri);
- if (name)
- return g_themed_icon_new (name);
-
- if (g_str_has_prefix (text_uri, "x-nautilus-search:"))
- return g_themed_icon_new ("folder-saved-search");
-
- /* gvfs doesn't give us a nice icon, so overriding */
- if (g_str_has_prefix (text_uri, "burn:"))
- return g_themed_icon_new ("nautilus-cd-burner");
-
- file = g_file_new_for_uri (text_uri);
-
- retval = shell_util_get_file_icon_if_mount (file);
- if (retval)
- return retval;
-
- /* gvfs doesn't give us a nice icon for subfolders of the trash, so
- * overriding */
- if (g_str_has_prefix (text_uri, "trash:"))
- {
- GFile *root;
-
- root = shell_util_get_gfile_root (file);
- g_object_unref (file);
- file = root;
- }
-
- info = g_file_query_info (file, "standard::icon", G_FILE_QUERY_INFO_NONE,
- NULL, NULL);
- g_object_unref (file);
-
- if (!info)
- return g_themed_icon_new ("gtk-file");
-
- retval = g_file_info_get_icon (info);
- if (retval)
- g_object_ref (retval);
- g_object_unref (info);
-
- if (retval)
- return retval;
-
- return g_themed_icon_new ("gtk-file");
-}
-
static void
stop_pick (ClutterActor *actor,
const ClutterColor *color)